#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include "thread.hpp"
#include "lockguard.hpp"
using namespace ThreadNS;

#define NUM 15

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *tpthis, std::string threadname)
        : _tpthis(tpthis), _threadname(threadname)
    {
    }

    ThreadPool<T> *_tpthis;
    std::string _threadname;
};

template <class T>
class ThreadPool
{
private:
    int _num;
    std::vector<Thread *> _threads; // 保存创建的线程
    std::queue<T> _task_queue;      // 保存任务列表
    pthread_mutex_t _mutex;         // 保护任务队列
    pthread_cond_t _cond;           // 线程阻塞的条件变量

private:
    static void *handlertask(void *args)
    {
        // sleep(3);
        // std::cout<<(args)<<std::endl;

        ThreadData<T> *data = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            // data->_tpthis->lockqueue();
            T t;
            {
                LockGuard lock(data->_tpthis->getmutex());
                while (data->_tpthis->queueempty())
                {
                    data->_tpthis->waitthread();
                }
                t = data->_tpthis->queuepop();
            }
            // data->_tpthis->unlockqueue();
            std::cout << data->_threadname << "处理任务：" << t() << std::endl;
        }
    }
    void lockqueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void unlockqueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    bool queueempty()
    {
        return _task_queue.empty();
    }
    void waitthread()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    T queuepop()
    {
        // 这个是内部接口
        // 不用加锁，因为在锁内部调用。
        T ret = _task_queue.front();
        _task_queue.pop();
        return ret;
    }
    void signalthread()
    {
        pthread_cond_signal(&_cond);
    }

    pthread_mutex_t *getmutex()
    {
        return &_mutex;
    }

public:
    ThreadPool(int num = NUM)
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _num; ++i)
        {

            Thread *tp = new Thread();
            _threads.push_back(tp);
        }
    }

    void start()
    {
        for (auto &e : _threads)
        {
            ThreadData<T> *data = new ThreadData<T>(this, e->getname());
            e->start(handlertask, (void *)data);
            // std::cout<<e<<" thread start.."<<std::endl;
        }
    }
    void push(T in)
    {
        // lockqueue();
        LockGuard lock = getmutex();
        _task_queue.push(in);
        std::cout << "收到任务：" << in.totaskstring() << std::endl;
        signalthread();
        // unlockqueue();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto &e : _threads)
        {
            e->join();
            delete e;
        }
    }
};

// 懒汉模式, 线程安全

// template <class T>
// class ThreadPool
// {
//     typedef void *(*func_t)(void *);
//     static void *handlerTask(void *args)
//     {

//         ThreadPool<T> *th = static_cast<ThreadPool<T> *>(args);
//         while(true)
//         {
//             pthread_mutex_lock(&(th->_mutex));

//             while(th->_task_queue.size() == 0)
//             {
//                 pthread_cond_wait(&(th->_cond) ,&(th->_mutex));
//             }
//             T t = th->_task_queue.front();
//             th->_task_queue.pop();
//             pthread_mutex_unlock(&(th->_mutex));
//             t();//处理任务
//         }
//         return nullptr;
//     }

// public:
//     ThreadPool(pthread_t num = NUM) : _num(num)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);

//         for (int i = 0; i < _num; i++) // 创建num个线程
//         {
//             _threads.push_back(new Thread(handlerTask, this));
//         }
//     }
//     void start()
//     {
//         for(int i =0 ; i< _threads.size();i++)
//         {
//             _threads[i]->start();
//             std::cout<<_threads[i]->getname()<<"start..."<<std::endl;
//         }
//     }

//     void* PushTask(const T& in)
//     {
//         pthread_mutex_lock(&_mutex);
//         _task_queue.push(in);
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }

//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//         for (auto &t : _threads)
//         {
//             t->join();
//             delete t;
//         }
//     }

// private:
//     std::vector<Thread *> _threads; // 存放线程
//     int _num;                       // 线程的多少
//     std::queue<T> _task_queue;      // 存放任务的队列
//     pthread_mutex_t _mutex;         // 所有线程必须互斥的访问我们的的任务队列。
//     pthread_cond_t _cond;           // 线程阻塞的条件变量。在这个条件变量下等待。
// };
